//*********************************************************
//
//    Copyright (c) Microsoft. All rights reserved.
//    This code is licensed under the Apache License, Version 2.0.
//    THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
//    ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
//    IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
//    PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//*********************************************************

using System;
using System.ComponentModel;
using System.Workflow.ComponentModel;
using System.Xml;

namespace Microsoft.Research.ScientificWorkflow.Activities
{
    [Name("XMLDoc Append")]
    [Description("Activity to append one Xml document to another.")]
    [WorkflowCategory("Utilities")]
    public class XmlDocAppend : Activity
    {
        #region Dependency Properties

        public static DependencyProperty SourceXmlDocProperty = DependencyProperty.Register("SourceXmlDoc",
            typeof(XmlDocument), typeof(XmlDocAppend));

        [RequiredInputParam]
        [Name("XmlDocument")]
        [Description("Xml Document from where to read the data.")]
        public XmlDocument SourceXmlDoc
        {
            get
            {
                return ((XmlDocument)(base.GetValue(XmlDocAppend.SourceXmlDocProperty)));
            }
            set
            {
                base.SetValue(XmlDocAppend.SourceXmlDocProperty, value);
            }
        }

        public static DependencyProperty SourceXQueryProperty = DependencyProperty.Register("SourceXQuery",
            typeof(string), typeof(XmlDocAppend));

        [InputParam]
        [Name("XPathQuery")]
        [Description("XPath query string for selecting the source node.")]
        public string SourceXQuery
        {
            get
            {
                return ((string)(base.GetValue(XmlDocAppend.SourceXQueryProperty)));
            }
            set
            {
                base.SetValue(XmlDocAppend.SourceXQueryProperty, value);
            }
        }

        public static DependencyProperty TargetXmlDocProperty = DependencyProperty.Register("TargetXmlDoc",
            typeof(XmlDocument), typeof(XmlDocAppend));

        [RequiredInputParam]
        [Name("XmlDocument")]
        [Description("Xml Document to which the node from source will be added to.")]
        public XmlDocument TargetXmlDoc
        {
            get
            {
                return ((XmlDocument)(base.GetValue(XmlDocAppend.TargetXmlDocProperty)));
            }
            set
            {
                base.SetValue(XmlDocAppend.TargetXmlDocProperty, value);
            }
        }

        public static DependencyProperty TargetXQueryProperty = DependencyProperty.Register("TargetXQuery",
            typeof(string), typeof(XmlDocAppend));

        [InputParam]
        [Name("XPathQuery")]
        [Description("XPath query string for selecting the target node.")]
        public string TargetXQuery
        {
            get
            {
                return ((string)(base.GetValue(XmlDocAppend.TargetXQueryProperty)));
            }
            set
            {
                base.SetValue(XmlDocAppend.TargetXQueryProperty, value);
            }
        }

        public static DependencyProperty MergedXmlDocProperty = DependencyProperty.Register("MergedXmlDoc",
            typeof(XmlDocument), typeof(XmlDocAppend));

        [OutputParam]
        [Name("XmlDocument")]
        [Description("Merged Xml Doc node.")]
        public XmlDocument MergedXmlDoc
        {
            get
            {
                return ((XmlDocument)(base.GetValue(XmlDocAppend.MergedXmlDocProperty)));
            }
            set
            {
                base.SetValue(XmlDocAppend.MergedXmlDocProperty, value);
            }
        }
        #endregion

        protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
        {
            if (null == this.TargetXmlDoc || null == this.TargetXQuery
                || null == this.SourceXmlDoc)
                return ActivityExecutionStatus.Faulting;

            XmlNode appendNode = null;
            if (!string.IsNullOrEmpty(this.SourceXQuery))
            {
                try
                {
                    appendNode = this.SourceXmlDoc.SelectSingleNode(this.SourceXQuery);
                }
                catch (Exception)
                {
                    appendNode = this.SourceXmlDoc.FirstChild;
                }
            }
            else
                appendNode = this.SourceXmlDoc.FirstChild;

            XmlNode targetNode = null;
            try
            {
                targetNode = this.TargetXmlDoc.SelectSingleNode(this.TargetXQuery);
            }
            catch (Exception)
            {
                targetNode = this.TargetXmlDoc.FirstChild;
            }

            targetNode.PrependChild(appendNode);
            this.MergedXmlDoc = this.TargetXmlDoc;
            return ActivityExecutionStatus.Closed;
        }

    }
}
